package com.tyf.common.web.controller.advice;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.tyf.common.exception.CanIgnoredException;
import com.tyf.common.vo.ResultVO;
import com.tyf.common.web.controller.annotation.FeignRestController;
import com.tyf.common.web.utils.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import com.tyf.common.exception.MyselfMsgException;
import com.tyf.common.util.CommonUtils;
import com.tyf.common.log.LogUtils;
import com.google.common.collect.Maps;


/**
 * 
 * FeignRestController请求,加装ResultVo 和 Data
 * 只针对RestController类
 */
@Order(1)
@RestControllerAdvice(annotations = {FeignRestController.class})
public class FeignRestControllerAdviceHandler implements ResponseBodyAdvice<Object>{
	
	private Logger logger = LoggerFactory.getLogger(FeignRestControllerAdviceHandler.class);
	
	
	/**
	 * 结果集转换增加ResultVo
	 */
	@Override
	public final Object beforeBodyWrite(Object body, MethodParameter returnType,
			MediaType contentType, Class<? extends HttpMessageConverter<?>> converterType,
			ServerHttpRequest request, ServerHttpResponse response){
		
		LogUtils.logDebug(logger,"add ResultMap.....");
		
		Map<String,Object> resultMap = WebUtils.getDefaultResultMap();
		resultMap.put("data", body);
		
		return resultMap;
	}

	@Override
	public boolean supports(MethodParameter returnType,
			Class<? extends HttpMessageConverter<?>> converterType) {
		// TODO Auto-generated method stub
		return true;
	}
	
	 /**
	 * 统一异常处理返回,只处理程序已确定的异常（Exception）<br>
	 * 未捕获的异常则走500页面的错误处理
	 * @param e 异常
	 * @param req http请求
	 * @return resultMap 封装的结果集map
	 */
	@ExceptionHandler({Exception.class})
	@ResponseBody
	public Object processCertainException(Exception e, HttpServletRequest req, HttpServletResponse response) {
		Map<String, Object> resultMap = Maps.newHashMap();
		ResultVO flag = new ResultVO();
		flag.setRetCode(ResultVO.ERROR_CODE); // 异常默认code

		// 异常处理
		if (e instanceof CanIgnoredException) { // 可忽略的异常
			flag.setRetCode(ResultVO.WARN_CODE);
			flag.setRetMsg(e.getMessage());
		} else if (e instanceof MyselfMsgException) { // 自定义异常
			flag.setRetMsg(e.getMessage());
		}else{
			//500 其它异常
    		setResponseError(e, response);
    		return CommonUtils.getStackTrace(e);
		}

		LogUtils.logInfo(e.getMessage(), e);
		// 返回结果
		resultMap.put("flag", flag);
		return resultMap;
	}
	
	/**
     * 设置返回错误
     * @param e exception
     * @param response http响应
     */
    protected void setResponseError(Exception e, HttpServletResponse response){
    	logger.error(">>>>>>>>Error:", e);
    	response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());	//异常统一返回500状态
    }
}
